package com.haixiaoke.saas.contract.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasc.open.api.v5_1.req.signtask.AddFillFieldInfo;
import com.fasc.open.api.v5_1.res.template.ActorInfo;
import com.fasc.open.api.v5_1.res.template.FillActorFieldInfo;
import com.fasc.open.api.v5_1.res.template.SignTaskActorInfo;
import com.fasc.open.api.v5_1.res.template.SignTemplateDetailRes;
import com.haixiaoke.saas.ali.service.AliAuthService;
import com.haixiaoke.saas.bill.domain.Bill;
import com.haixiaoke.saas.bill.domain.BillItem;
import com.haixiaoke.saas.bill.service.IBillItemService;
import com.haixiaoke.saas.bill.service.IBillService;
import com.haixiaoke.saas.common.constant.*;
import com.haixiaoke.saas.common.contract.domain.ElectronicVisaContract;
import com.haixiaoke.saas.common.core.domain.AjaxResult;
import com.haixiaoke.saas.common.utils.DateUtils;
import com.haixiaoke.saas.contract.domain.Contract;
import com.haixiaoke.saas.contract.mapper.ContractMapper;
import com.haixiaoke.saas.contract.service.IContractService;
import com.haixiaoke.saas.fadada.service.FaDaDaService;
import com.haixiaoke.saas.house.domain.House;
import com.haixiaoke.saas.house.service.IHouseService;
import com.haixiaoke.saas.lock.domain.DeviceLock;
import com.haixiaoke.saas.lock.domain.LockFace;
import com.haixiaoke.saas.lock.service.IDeviceLockService;
import com.haixiaoke.saas.lock.service.ILockFaceService;
import com.haixiaoke.saas.tenant.domain.ElectronicVisa;
import com.haixiaoke.saas.tenant.domain.Tenant;
import com.haixiaoke.saas.tenant.service.IElectronicVisaService;
import com.haixiaoke.saas.tenant.service.ITenantService;
import com.haixiaoke.saas.user.domain.UserConsumer;
import com.haixiaoke.saas.user.service.IUserConsumerService;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 合同Service业务层处理
 *
 * @author panda
 * @date 2025-06-26
 */
@Service
public class ContractServiceImpl implements IContractService {
    @Autowired
    private ContractMapper contractMapper;
    @Autowired
    private AliAuthService aliAuthService;
    @Autowired
    private IUserConsumerService userConsumerService;
    @Autowired
    private FaDaDaService faDaDaService;
    @Autowired
    private IHouseService houseService;
    @Autowired
    private IElectronicVisaService electronicVisaService;
    @Autowired
    private IDeviceLockService deviceLockService;
    @Autowired
    private ILockFaceService lockFaceService;
    @Autowired
    private IBillService billService;
    @Autowired
    private IBillItemService billItemService;
    @Autowired
    private ITenantService tenantService;

    /**
     * 查询合同
     *
     * @param contractId 合同主键
     * @return 合同
     */
    @Override
    public Contract selectContractByContractId(String contractId) {
        return contractMapper.selectContractByContractId(contractId);
    }

    /**
     * 查询合同列表
     *
     * @param contract 合同
     * @return 合同
     */
    @Override
    public List<Contract> selectContractList(Contract contract) {
        return contractMapper.selectContractList(contract);
    }

    /**
     * 新增合同
     *
     * @param contract 合同
     * @return 结果
     */
    @Override
    @Transactional
    public AjaxResult insertContract(Contract contract) {
        if (StrUtil.isEmpty(contract.getHouseId())) {
            return AjaxResult.warn("请选择房源");
        }
        if (ObjectUtil.isEmpty(contract.getContractStartDate()) || ObjectUtil.isEmpty(contract.getContractEndDate())) {
            return AjaxResult.warn("请选择合同周期");
        }
        if (StrUtil.equals(ContractConstants.CONTRACT_TYPE_ELECTRONIC, contract.getContractType()) &&
                contract.getContractTemplateId() == null) {
            return AjaxResult.warn("请选择合同模板");
        }
        if (ObjectUtil.isNotEmpty(contract.getFreeRentStartDate()) && ObjectUtil.isNotEmpty(contract.getFreeRentEndDate())) {
            if (contract.getFreeRentEndDate().after(contract.getContractStartDate())) {
                return AjaxResult.warn("免租周期不能大于合同周期");
            }
        }
        int check = contractMapper.checkContract(contract);
        if (check > 0) {
            return AjaxResult.warn("合同已存在");
        }
        House house = houseService.selectHouseByHouseId(contract.getHouseId());
        if (ObjectUtil.isEmpty(house)) {
            return AjaxResult.warn("房源不存在");
        }
        long day = DateUtil.betweenDay(contract.getContractStartDate(), contract.getContractEndDate(), true);
        if (house.getLeasePeriod() > day) {
            return AjaxResult.warn("租期不能小于房屋租期");
        }

        ElectronicVisa electronicVisa = electronicVisaService.selectElectronicVisaByTenantId(contract.getTenantId());
        if (ObjectUtil.isEmpty(electronicVisa) ||
                StrUtil.equals(TenantConstants.AUTH_TYPE_NO, electronicVisa.getAuthType())) {
            return AjaxResult.warn("请完成电子签认证");
        }

        if (!aliAuthService.identityCheck(contract.getContactName(), contract.getIdCardNo())) {
            return AjaxResult.warn("身份证信息不正确");
        }

        String contractId = "C" + System.currentTimeMillis() + RandomUtils.nextInt(10000, 100000);

        Date nowDate = DateUtils.getNowDate();
        UserConsumer userConsumer = userConsumerService.selectUserConsumerByPhone(contract.getContactPhone());
        if (ObjectUtil.isEmpty(userConsumer)) {
            userConsumer = new UserConsumer();
            userConsumer.setUserPhone(contract.getContactPhone());
            userConsumer.setUserName(contract.getContactName());
            userConsumer.setCardNumber(contract.getIdCardNo());
            userConsumer.setCreateBy(contract.getCreateBy());
            userConsumerService.insertUserConsumer(userConsumer);
        } else {
            userConsumer.setUserName(contract.getContactName());
            userConsumer.setCardNumber(contract.getIdCardNo());
            userConsumer.setUpdateTime(nowDate);
            userConsumer.setUpdateBy(contract.getCreateBy());
            userConsumerService.updateUserConsumer(userConsumer);
        }
        if (StrUtil.equals(ContractConstants.CONTRACT_TYPE_ELECTRONIC, contract.getContractType())) {
            // 电子签
            SignTemplateDetailRes signTemplateDetail = faDaDaService.getSignTemplateDetail(contract.getContractTemplateId());
            List<SignTaskActorInfo> actors = signTemplateDetail.getActors();
            List<AddFillFieldInfo> partyAs = new ArrayList<>();
            List<AddFillFieldInfo> partyBs = new ArrayList<>();
            for (SignTaskActorInfo actor : actors) {
                // ActorInfo actorInfo = actor.getActorInfo();
                // Boolean initiator = actorInfo.getInitiator();
                // if (initiator) {
                // }
                List<AddFillFieldInfo> list = new ArrayList<>();
                List<FillActorFieldInfo> fillFields = actor.getFillFields();
                if (CollectionUtil.isNotEmpty(fillFields)) {
                    for (FillActorFieldInfo fillField : fillFields) {
                        AddFillFieldInfo info = new AddFillFieldInfo();
                        info.setFieldDocId(fillField.getFieldDocId().toString());
                        info.setFieldValue(buildValue(fillField.getFieldId(), contract, house, electronicVisa));
                        info.setFieldId(fillField.getFieldId());
                        info.setFieldName(faDaDaService.buildFieldName(fillField.getFieldId()));
                        list.add(info);
                    }
                }
                ActorInfo actorInfo = actor.getActorInfo();
                //“甲方”，“乙方”的参与方的标识内容
                String actorId = actorInfo.getActorId();
                if (StrUtil.equals(actorId, "甲方")) {
                    partyAs.addAll(list);
                } else if (StrUtil.equals(actorId, "乙方")) {
                    partyBs.addAll(list);
                }
            }
            ElectronicVisaContract electronicVisaContract = buildElectronicVisaContract(partyAs, partyBs, contract, electronicVisa);
            // 签署任务id
            String signTaskId = faDaDaService.createWithTemplate(electronicVisaContract);
            contract.setFlowId(signTaskId);
        }
        contract.setConUserId(userConsumer.getUserId());
        contract.setCreateTime(nowDate);
        contract.setContractId(contractId);
        contract.setContractState(ContractConstants.CONTRACT_STATE_TO_BE_SIGNED);
        int result = contractMapper.insertContract(contract);
        if (result > 0) {
            Tenant tenant = tenantService.selectDepByDepId(contract.getTenantId());
            if (StrUtil.equals(TenantConstants.GENERATE_BILL_YES, tenant.getGenerateBillState())) {
                List<Bill> billList = new ArrayList<>();
                List<BillItem> billItemList = new ArrayList<>();
                List<Map<String, Object>> maps = billService.buildCycle(contract);
                // 使用中文Locale和自定义模式
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月", Locale.CHINESE);
                for (Map<String, Object> map : maps) {
                    String billId = "B" + System.currentTimeMillis() + RandomUtils.nextInt(10000, 100000);
                    Date startTime = (Date) map.get("startTime");
                    String name = sdf.format(startTime) + "租金";
                    Bill bill = new Bill();
                    bill.setBillId(billId);
                    bill.setBillName(name);
                    bill.setContractId(contractId);
                    bill.setHouseId(house.getHouseId());
                    bill.setBillAmount(house.getRent());
                    bill.setCreateTime(nowDate);
                    bill.setBillStartDate(startTime);
                    bill.setBillEndDate((Date) map.get("endTime"));
                    bill.setBillState(BillConstants.BILL_STATE_UNPAID);
                    bill.setConUserId(contract.getConUserId());
                    bill.setTenantId(contract.getTenantId());
                    billList.add(bill);

                    BillItem billItem = new BillItem();
                    billItem.setBillId(billId);
                    billItem.setItemName(name);
                    billItem.setItemAmount(house.getRent());
                    billItemList.add(billItem);
                }

                billService.insertBatchBill(billList);
                billItemService.insertBatchBillItem(billItemList);
            }
            return AjaxResult.success();
        }
        return AjaxResult.error();
    }

    /**
     * 封装电子合同参数
     *
     * @param fieldId
     * @return
     */
    public String buildValue(String fieldId, Contract contract, House house, ElectronicVisa electronicVisa) {
        String fieldValue = "";
        switch (fieldId) {
            case TencentContractTemplateModule.HOUSE_ADDRESS:
                fieldValue = house.getAddress();
                break;
            case TencentContractTemplateModule.ORG_NAME:
                fieldValue = electronicVisa.getOrganizationName();
                break;
            case TencentContractTemplateModule.USCC:
                fieldValue = electronicVisa.getSocialCreditCode();
                break;
            case TencentContractTemplateModule.HOUSE_TYPE:
                fieldValue = house.getRoomType();
                break;
            case TencentContractTemplateModule.AREA:
                fieldValue = house.getHouseArea() + "m²";
                break;
            case TencentContractTemplateModule.USER_NAME:
                fieldValue = contract.getContactName();
                break;
            case TencentContractTemplateModule.ID_CARD:
                fieldValue = contract.getIdCardNo();
                break;
            case TencentContractTemplateModule.USER_PHONE:
                fieldValue = contract.getContactPhone();
                break;
            case TencentContractTemplateModule.LEASE_START_TIME:
                fieldValue = DateUtil.format(contract.getContractStartDate(), "yyyy-MM-dd");
                break;
            case TencentContractTemplateModule.LEASE_END_TIME:
                fieldValue = DateUtil.format(contract.getContractEndDate(), "yyyy-MM-dd");
                break;
            default:
                break;
        }
        return fieldValue;
    }

    /**
     * @param partyAList     甲方合同组件信息
     * @param partyBList     乙方合同组件信息
     * @param contract       合同内容
     * @param electronicVisa 电子签信息
     * @return
     */
    private ElectronicVisaContract buildElectronicVisaContract(List<AddFillFieldInfo> partyAList, List<AddFillFieldInfo> partyBList,
                                                               Contract contract, ElectronicVisa electronicVisa) {
        ElectronicVisaContract electronicVisaContract = new ElectronicVisaContract();
        electronicVisaContract.setTemplateId(contract.getContractTemplateId());
        electronicVisaContract.setName(contract.getContactName());
        electronicVisaContract.setMobile(contract.getContactPhone());
        electronicVisaContract.setIdCard(contract.getIdCardNo());
        electronicVisaContract.setAFillFieldList(partyAList);
        electronicVisaContract.setBFillFieldList(partyBList);
        electronicVisaContract.setExpiresTime(contract.getLatestSigningDate());
        electronicVisaContract.setActorName(electronicVisa.getOrganizationName());
        electronicVisaContract.setOpenId(electronicVisa.getOpenId());
        return electronicVisaContract;
    }

    /**
     * 修改合同
     *
     * @param contract 合同
     * @return 结果
     */
    @Override
    public int updateContract(Contract contract) {
        contract.setUpdateTime(DateUtils.getNowDate());
        return contractMapper.updateContract(contract);
    }

    /**
     * 批量删除合同
     *
     * @param contractIds 需要删除的合同主键
     * @return 结果
     */
    @Override
    public int deleteContractByContractIds(String[] contractIds) {
        return contractMapper.deleteContractByContractIds(contractIds);
    }

    /**
     * 删除合同信息
     *
     * @param contractId 合同主键
     * @return 结果
     */
    @Override
    public int deleteContractByContractId(String contractId) {
        return contractMapper.deleteContractByContractId(contractId);
    }

    /**
     * 上传合同图片
     *
     * @param contract
     * @return
     */
    @Override
    public AjaxResult uploadContractImage(Contract contract) {
        if (CollectionUtil.isEmpty(contract.getContractPictureList())) {
            return AjaxResult.error("请上传合同图片");
        }
        if (contract.getContractPictureList().size() > 9) {
            return AjaxResult.error("合同图片不能超过9张");
        }
        Contract contractById = contractMapper.selectContractByContractId(contract.getContractId());

        if (ObjectUtil.isNotEmpty(contractById)) {
            if (!StrUtil.equals(contractById.getTenantId(), contract.getTenantId())) {
                return AjaxResult.error("不能操作其他机构的合同");
            }
            if (StrUtil.equals(ContractConstants.CONTRACT_TYPE_ELECTRONIC, contractById.getContractType())) {
                return AjaxResult.error("电子合同不支持上传图片");
            }
            if (!StrUtil.equals(ContractConstants.CONTRACT_STATE_TO_BE_SIGNED, contractById.getContractState())) {
                return AjaxResult.warn("合同状态异常，请刷新后再试");
            }
            contract.setContractPicture(StringUtils.join(contract.getContractPictureList(), ","));
            contract.setContractState(ContractConstants.CONTRACT_STATE_SIGN_OFF);
            contract.setUpdateTime(DateUtils.getNowDate());
            contractMapper.updateContract(contract);
            return AjaxResult.success();
        }
        return AjaxResult.error("合同不存在");
    }

    @Override
    public AjaxResult signingContract(Contract contract, Boolean participantType) {
        Contract contractById = contractMapper.selectContractByContractId(contract.getContractId());

        if (ObjectUtil.isNotEmpty(contractById)) {
            if (participantType && !StrUtil.equals(contractById.getTenantId(), contract.getTenantId())) {
                return AjaxResult.error("不能操作其他机构的合同");
            }
            if (StrUtil.equals(ContractConstants.CONTRACT_TYPE_PAPER, contractById.getContractType())) {
                return AjaxResult.warn("纸质合同不支持签约");
            }
            if (StrUtil.isBlank(contractById.getFlowId())) {
                return AjaxResult.warn("该合同数据错误，无法签约");
            }

            String actorUrl = faDaDaService.getActorUrl(contractById.getFlowId(), contract.getRedirectUrl(), participantType);
            return StrUtil.isBlank(actorUrl) ? AjaxResult.error("数据异常，请联系管理员") : AjaxResult.success("操作成功", actorUrl);
        }
        return AjaxResult.error();
    }

    @Override
    public AjaxResult selectContractPreviewUrl(Contract contract) {
        Contract contractById = contractMapper.selectContractByContractId(contract.getContractId());
        if (ObjectUtil.isNotEmpty(contractById) && ContractConstants.CONTRACT_TYPE_ELECTRONIC.equals(contractById.getContractType())) {
            return AjaxResult.success("操作成功", faDaDaService.getSignTaskPreviewUrl(contractById.getFlowId(), contract.getRedirectUrl()));
        }
        return AjaxResult.error();
    }

    @Override
    @Transactional
    public AjaxResult checkIn(String contractId, String username, String tenantId) {
        Contract contract = contractMapper.selectContractByContractId(contractId);
        if (ObjectUtil.isEmpty(contract)) {
            return AjaxResult.error("合同不存在");
        }
        if (!StrUtil.equals(contract.getTenantId(), tenantId)) {
            return AjaxResult.error("不能操作其他机构的合同");
        }
        Date nowDate = DateUtils.getNowDate();
        //当前时间在预约开始时间之前,或当前时间在预约结束时间之后,则不可入住
        if (ObjectUtil.isEmpty(contract.getFreeRentStartDate()) && ObjectUtil.isEmpty(contract.getFreeRentEndDate())) {
            if (nowDate.before(contract.getContractStartDate()) || nowDate.after(contract.getContractEndDate())) {
                return AjaxResult.error("当前时间不在预约时间范围内，不可入住");
            }
        } else {
            if (nowDate.before(contract.getFreeRentStartDate()) || nowDate.after(contract.getFreeRentEndDate())) {
                if (nowDate.before(contract.getContractStartDate()) || nowDate.after(contract.getContractEndDate())) {
                    return AjaxResult.error("当前时间不在免租时间范围以及预约时间范围内，不可入住");
                }
            }
        }
        if (!StrUtil.equals(ContractConstants.CONTRACT_STATE_SIGN_OFF, contract.getContractState())) {
            return AjaxResult.error("合同状态异常，请刷新后再试");
        }
        DeviceLock lock = deviceLockService.selectDeviceLockByHouseId(contract.getHouseId());
        if (ObjectUtil.isNotEmpty(lock)) {
            int result = lockFaceService.checkUser(lock.getLockId());
            if (result > 0) {
                return AjaxResult.error("请先清除该房屋的设备锁的授权数据");
            }
            LockFace face = new LockFace();
            face.setLockId(lock.getLockId());
            face.setUserName(contract.getContactName());
            face.setUserPhone(contract.getContactPhone());
            face.setAuthTimeType(DeviceLockConstants.AUTH_TIME_TYPE_SHORT);
            face.setAuthStartTime(contract.getContractStartDate());
            face.setAuthEndTime(contract.getContractEndDate());
            face.setConUserId(contract.getConUserId());
            face.setLesseeFlag(DeviceLockConstants.LESSEE_FLAG_YES);
            AjaxResult ajaxResult = lockFaceService.contractInsertLockFace(face);
            if ((int) ajaxResult.get("code") != 200) {
                return ajaxResult;
            }
        }
        Contract newContract = new Contract();
        newContract.setContractId(contractId);
        newContract.setContractState(ContractConstants.CONTRACT_STATE_CHECK_IN);
        newContract.setUpdateBy(username);
        newContract.setUpdateTime(nowDate);
        int result = contractMapper.updateContract(newContract);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public Contract selectContractByFlowId(String flowId) {
        return contractMapper.selectContractByFlowId(flowId);
    }

    @Override
    public List<Map<String, Date>> checkTime(String houseId) {
        return contractMapper.checkTime(houseId);
    }

    @Override
    public Contract selectContractByHouseId(String houseId) {
        return contractMapper.selectContractByHouseId(houseId);
    }
}
